package com.duobaoyu.dby.supply.biz.strategy.message.order.confirm;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.duobaoyu.dby.channel.adapter.bean.message.order.OrderMessage;
import com.duobaoyu.dby.channel.adapter.enums.BizMessageTypeEnum;
import com.duobaoyu.dby.channel.adapter.enums.ChannelCodeEnum;
import com.duobaoyu.dby.channel.boundary.bean.order.param.OrderInfoParam;
import com.duobaoyu.dby.channel.boundary.bean.order.result.OrderInfoResult;
import com.duobaoyu.dby.channel.boundary.template.SupplyChannelTemplate;
import com.duobaoyu.dby.common.mybatis.config.IdGeneratorSnowflake;
import com.duobaoyu.dby.supply.biz.enums.OrderParentTypeEnum;
import com.duobaoyu.dby.supply.biz.producer.SupplyChainMQProducer;
import com.duobaoyu.dby.supply.biz.strategy.message.order.base.BaseOrderAsyncHandler;
import com.duobaoyu.dby.supply.common.biz.bo.message.ChannelMessageBO;
import com.duobaoyu.dby.supply.db.entity.order.Order;
import com.duobaoyu.dby.supply.db.entity.order.OrderConsignee;
import com.duobaoyu.dby.supply.db.entity.order.OrderProduct;
import com.duobaoyu.dby.supply.db.repository.order.OrderConsigneeRepository;
import com.duobaoyu.dby.supply.db.repository.order.OrderProductRepository;
import com.duobaoyu.dby.supply.db.repository.order.OrderRepository;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.List;
import java.util.Objects;
import java.util.Set;

@Slf4j
@Component
@RequiredArgsConstructor
public class OrderConfirmSplitChangeAsyncHandler extends BaseOrderAsyncHandler {

	private final OrderRepository orderRepository;
	private final TransactionTemplate transactionTemplate;
	private final IdGeneratorSnowflake idGeneratorSnowflake;
	private final SupplyChannelTemplate supplyChannelTemplate;
	private final SupplyChainMQProducer supplyChainMQProducer;
	private final OrderProductRepository orderProductRepository;
	private final OrderConsigneeRepository orderConsigneeRepository;


	@Override
	protected Set<String> channelCodes() {
		return Sets.newHashSet(ChannelCodeEnum.ALIBABA_DISTRIBUTION.getValue());
	}

	@Override
	protected Set<Integer> bizMessageTypes() {
		return Sets.newHashSet(BizMessageTypeEnum.CONFIRM_ORDER.getValue());
	}

	@Override
	protected Boolean executeHandler(ChannelMessageBO channelMessage, Object beforeResult) {
		OrderMessage orderMessage = JSON.parseObject(channelMessage.getMessage(), OrderMessage.class);
		Order order = orderRepository.getOne(Wrappers.<Order>lambdaQuery().eq(Order::getChannelTradeOrderSn, orderMessage.getChannelTradeOrderSn())
				.eq(Order::getChannelCode, channelMessage.getChannelCode()));

		if (ObjectUtils.isEmpty(order)) {
			log.info("message:{},channelCode:{},data:{}","确认回调失败",channelMessage.getChannelCode(),JSON.toJSONString(channelMessage));
			return Boolean.FALSE;
		}

		this.orderStateCheck(order);

		List<OrderProduct> orderProductList = orderProductRepository.list(Wrappers.<OrderProduct>lambdaQuery().eq(OrderProduct::getOrderSn, order.getOrderSn()));
		OrderConsignee orderConsignee = orderConsigneeRepository.getOne(Wrappers.<OrderConsignee>lambdaQuery().eq(OrderConsignee::getOrderSn, order.getOrderSn()));

		List<Order> orderList = Lists.newArrayList();
		List<OrderProduct> orderProductCopyList = Lists.newArrayList();
		List<OrderConsignee> orderConsigneeList = Lists.newArrayList();

		OrderInfoParam orderInfoParam = new OrderInfoParam();
		orderInfoParam.setChannelCode(ChannelCodeEnum.ALIBABA_DISTRIBUTION.getValue());
		orderInfoParam.setChannelTradeOrderSn(orderMessage.getChannelTradeOrderSn());
		OrderInfoResult orderInfo = supplyChannelTemplate.getOrderInfo(orderInfoParam);
		for (OrderInfoResult.RealOrderDetail realOrderDetail : orderInfo.getRealOrderDetailList()) {

			List<OrderProduct> orderProductNewList = Lists.newArrayList();
			for (OrderProduct orderProduct : orderProductList) {
				for (OrderInfoResult.RealOrderDetail.RealOrderSkuInfo realOrderSkuInfo : realOrderDetail.getSkuInfos()) {
					Boolean channelProductCode = StringUtils.isNotBlank(realOrderSkuInfo.getChannelProductCode()) ? Objects.equals(orderProduct.getChannelProductCode(),realOrderSkuInfo.getChannelProductCode()) : Boolean.TRUE;
					Boolean channelSkuCode = StringUtils.isNotBlank(realOrderSkuInfo.getChannelSkuCode()) ? Objects.equals(orderProduct.getChannelSkuCode(),realOrderSkuInfo.getChannelSkuCode()) : Boolean.TRUE;
					if(channelProductCode && channelSkuCode){
						orderProductNewList.add(orderProduct);
					}
				}
			}
			reckon(orderProductNewList);
			Order clone = order.clone();
			Order orderNew = createOrder(clone, orderProductNewList);
			orderNew.setChannelOrderSn(realOrderDetail.getChannelOrderSn());
			orderNew.setChannelOrderParentSn(order.getChannelTradeOrderSn());

			OrderConsignee orderConsigneeClone = orderConsignee.clone();
			orderConsigneeClone.setId(idGeneratorSnowflake.snowflakeId());
			orderConsigneeClone.setOrderSn(orderNew.getOrderSn());

			orderProductNewList.forEach(orderProduct -> orderProduct.setOrderSn(orderNew.getOrderSn()));

			orderList.add(orderNew);
			orderProductCopyList.addAll(orderProductNewList);
			orderConsigneeList.add(orderConsigneeClone);
		}

		transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			@Override
			protected void doInTransactionWithoutResult(@NotNull TransactionStatus transactionStatus) {
				orderRepository.saveBatch(orderList);
				orderProductRepository.saveBatch(orderProductCopyList);
				orderConsigneeRepository.saveBatch(orderConsigneeList);
				orderRepository.update(Wrappers.<Order>lambdaUpdate().set(Order::getParentType, OrderParentTypeEnum.BEFORE_SPLIT.getValue())
						.eq(Order::getId, order.getId()));
			}
		});
		supplyChainMQProducer.orderAlterSend(order.getSupplyTradeSn(), order.getServerName());
		return Boolean.TRUE;
	}
}
